#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QDebug>
#include "OpenXLSX/OpenXLSX.hpp"
#include <iostream>
#include <cmath>
#include <QFileDialog>
#include <QMessageBox>
#include <QProcess>

using namespace std;
using namespace OpenXLSX;

QMap<emDefinedString, QString>g_mapDefinedString = {
    {ts, "TS"},
    {version, "version"},
    {language, "language"},
    {context, "context"},
    {name, "name"},
    {mac_menu, "MAC_APPLICATION_MENU"},
    {trans_object, "QObject"},
    {trans_text, "TransText"},
    {message, "message"},
    {location, "location"},
    {filename, "filename"},
    {line, "line"},
    {source, "source"},
    {translation, "translation"},
    {type, "type"},
    {vanished, "vanished"}
};

QMap<QString, QString>g_mapTsName = {
    {QStringLiteral("阿拉伯语"), "translation_ar.ts"},
    {QStringLiteral("丹麦语"), "translation_da.ts"},
    {QStringLiteral("德语"),  "translation_de.ts"},
    {QStringLiteral("希腊语"),  "translation_el.ts"},
    {QStringLiteral("西班牙语"),  "translation_es.ts"},
    {QStringLiteral("芬兰语"),  "translation_fi.ts"},
    {QStringLiteral("法语"),  "translation_fr.ts"},
    {QStringLiteral("希伯来语"),  "translation_he.ts"},
    {QStringLiteral("印地语"),  "translation_hi.ts"},
    {QStringLiteral("克罗地亚语"),  "translation_id.ts"},
    {QStringLiteral("意大利语"),  "translation_it.ts"},
    {QStringLiteral("日本语"),  "translation_ja.ts"},
    {QStringLiteral("韩语"),  "translation_ko.ts"},
    {QStringLiteral("立陶宛语"),  "translation_fr.ts"},
    {QStringLiteral("波兰语"),  "translation_pl.ts"},
    {QStringLiteral("葡萄牙语"),  "translation_pt.ts"},
    {QStringLiteral("俄语"),  "translation_ru.ts"},
    {QStringLiteral("土耳其语"),  "translation_tr.ts"},
    {QStringLiteral("乌克兰语"),  "translation_uk.ts"},
    {QStringLiteral("越南语"),  "translation_vi.ts"},
    {QStringLiteral("台湾"),  "translation_tw.ts"}
};

QList<QDomNode> ParseXmlData::findDomElement(QDomNode inElem, const QString& nodeName) {
    QList<QDomNode> list;
    list.clear();
    QDomNodeList lstChildren = inElem.childNodes();
    for (int i = 0, iSize = lstChildren.size(); i < iSize; ++i) {
        if(lstChildren.at(i).nodeName() == nodeName) {
            qDebug() << lstChildren.at(i).toElement().text();
            list << lstChildren.at(i);
        }
    }

    return list;
}

bool ParseXmlData::parseTsFile(const QString& ts_file)
{
    QFile file(ts_file);
    if(!file.exists())
        return false;

    QDomDocument dom;
    if(!dom.setContent(&file))
        return false;

    QDomElement domRoot = dom.documentElement();
    QString strEleName = domRoot.nodeName();
    if (strEleName == g_mapDefinedString[ts]) {
        m_version = domRoot.hasAttribute(g_mapDefinedString[version]) ? domRoot.attribute(g_mapDefinedString[version]) : "";
        m_language = domRoot.hasAttribute(g_mapDefinedString[language]) ? domRoot.attribute(g_mapDefinedString[language]) : "";
        auto domList = findDomElement(domRoot, g_mapDefinedString[context]);
         for (int i = 0; i < domList.size(); ++i) {
            auto nameList = findDomElement(domList.at(i), g_mapDefinedString[name]);
            if(nameList.size() < 1)
                continue;
            auto dom = nameList.at(0);
            QString name = dom.toElement().text();
            if(name == g_mapDefinedString[mac_menu]) {
                auto messageList = findDomElement(domList.at(i), g_mapDefinedString[message]);
                for (int i = 0; i < messageList.size(); ++i) {
                    TranslateMessage message;
                    message.name = g_mapDefinedString[mac_menu];
                    message.locationInfo.clear();
                    auto sourceList = findDomElement(messageList.at(i), g_mapDefinedString[source]);
                    if(sourceList.size() > 0)
                        message.source = sourceList.at(0).toElement().text();
                    auto translationList = findDomElement(messageList.at(i), g_mapDefinedString[translation]);
                    if(translationList.size() > 0)
                        message.translation = translationList.at(0).toElement().text();
                    m_vector.push_back(message);
                }
            } else if(name == g_mapDefinedString[trans_object] || name == g_mapDefinedString[trans_text]) {
                auto messageList = findDomElement(domList.at(i), g_mapDefinedString[message]);
                for (int i = 0; i < messageList.size(); ++i) {
                    TranslateMessage message;
                    message.name = name;
                    auto locationList = findDomElement(messageList.at(i), g_mapDefinedString[location]);
                    for (int idx = 0; idx < locationList.size(); ++idx) {
                        LocationInfo info;
                        info.filename = locationList.at(idx).toElement().hasAttribute(g_mapDefinedString[filename]) \
                            ? locationList.at(idx).toElement().attribute(g_mapDefinedString[filename]) : "";
                        info.line = locationList.at(idx).toElement().hasAttribute(g_mapDefinedString[line]) \
                            ?  locationList.at(idx).toElement().attribute(g_mapDefinedString[line]) : "";
                        message.locationInfo.push_back(info);
                    }
                    auto sourceList = findDomElement(messageList.at(i), g_mapDefinedString[source]);
                    if(sourceList.size() > 0)
                        message.source = sourceList.at(0).toElement().text();
                    auto translationList = findDomElement(messageList.at(i), g_mapDefinedString[translation]);
                    if(translationList.size() > 0)
                        message.translation = translationList.at(0).toElement().text();
                    m_vector.push_back(message);
                }
            }
        }
    }

    file.close();
    return true;
}

bool ParseXmlData::writeTsFile(const QString& ts_file)
{
    QDomDocument tsDoc;
    QDomProcessingInstruction xmlProcess = tsDoc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
    tsDoc.appendChild(xmlProcess);

    QDomElement tsRoot = tsDoc.createElement(g_mapDefinedString[ts]);
     tsRoot.setAttribute(g_mapDefinedString[version], m_version);
     tsRoot.setAttribute(g_mapDefinedString[language], m_language);
    QDomElement tsMenuContext = tsDoc.createElement(g_mapDefinedString[context]);
     QDomElement tsStringContext = tsDoc.createElement(g_mapDefinedString[context]);
    QDomElement tsTextContext = tsDoc.createElement(g_mapDefinedString[context]);
     bool bFirstEnterMenu = true;
     bool bFirstEnterString = true;
     bool bFirstEnterText = true;

     for (int idx = 0; idx < m_vector.size(); idx++) {
        if(m_vector[idx].name == g_mapDefinedString[mac_menu]) {
            QDomElement tsName = tsDoc.createElement(g_mapDefinedString[name]);
            QDomElement tsLocation = tsDoc.createElement(g_mapDefinedString[location]);
            QDomElement tsSource = tsDoc.createElement(g_mapDefinedString[source]);
            QDomElement tsTranslation = tsDoc.createElement(g_mapDefinedString[translation]);
            QDomElement tsMessge = tsDoc.createElement(g_mapDefinedString[message]);

            QDomText text;
            text = tsDoc.createTextNode(g_mapDefinedString[mac_menu]);
            tsName.appendChild(text);
            text = tsDoc.createTextNode(m_vector[idx].source);
            tsSource.appendChild(text);
            text = tsDoc.createTextNode(m_vector[idx].translation);
            tsTranslation.appendChild(text);
            tsTranslation.setAttribute(g_mapDefinedString[type], g_mapDefinedString[vanished]);
            tsMessge.appendChild(tsSource);
            tsMessge.appendChild(tsTranslation);

            if(bFirstEnterMenu) {
                bFirstEnterMenu = false;
                tsMenuContext.appendChild(tsName);
            }
            tsMenuContext.appendChild(tsMessge);
        }
        else if(m_vector[idx].name == g_mapDefinedString[trans_object]) {
            QDomElement tsName = tsDoc.createElement(g_mapDefinedString[name]);
            QDomElement tsSource = tsDoc.createElement(g_mapDefinedString[source]);
            QDomElement tsTranslation = tsDoc.createElement(g_mapDefinedString[translation]);
            QDomElement tsMessge = tsDoc.createElement(g_mapDefinedString[message]);

            QDomText text;
            text = tsDoc.createTextNode(m_vector[idx].name);
            tsName.appendChild(text);
            for(int i = 0 ; i<m_vector[idx].locationInfo.size(); i++) {
                QDomElement tsLocation = tsDoc.createElement(g_mapDefinedString[location]);
                if(!m_vector[idx].locationInfo[i].filename.isEmpty() && !m_vector[idx].locationInfo[i].line.isEmpty()) {
                    tsLocation.setAttribute(g_mapDefinedString[filename], m_vector[idx].locationInfo[i].filename);
                    tsLocation.setAttribute(g_mapDefinedString[line], m_vector[idx].locationInfo[i].line);
                    tsMessge.appendChild(tsLocation);
                }
            }

            text = tsDoc.createTextNode(m_vector[idx].source);
            tsSource.appendChild(text);
            text = tsDoc.createTextNode(m_vector[idx].translation);
            tsTranslation.appendChild(text);
            tsMessge.appendChild(tsSource);
            tsMessge.appendChild(tsTranslation);

            if(bFirstEnterString) {
                bFirstEnterString = false;
                tsStringContext.appendChild(tsName);
            }
            tsStringContext.appendChild(tsMessge);
        }
        else if(m_vector[idx].name == g_mapDefinedString[trans_text]) {
            QDomElement tsName = tsDoc.createElement(g_mapDefinedString[name]);
            QDomElement tsSource = tsDoc.createElement(g_mapDefinedString[source]);
            QDomElement tsTranslation = tsDoc.createElement(g_mapDefinedString[translation]);
            QDomElement tsMessge = tsDoc.createElement(g_mapDefinedString[message]);

            QDomText text;
            text = tsDoc.createTextNode(m_vector[idx].name);
            tsName.appendChild(text);
            for(int i = 0 ; i<m_vector[idx].locationInfo.size(); i++) {
                QDomElement tsLocation = tsDoc.createElement(g_mapDefinedString[location]);
                tsLocation.setAttribute(g_mapDefinedString[filename], m_vector[idx].locationInfo[i].filename);
                tsLocation.setAttribute(g_mapDefinedString[line], m_vector[idx].locationInfo[i].line);
                tsMessge.appendChild(tsLocation);
            }

            text = tsDoc.createTextNode(m_vector[idx].source);
            tsSource.appendChild(text);
            text = tsDoc.createTextNode(m_vector[idx].translation);
            tsTranslation.appendChild(text);
            tsMessge.appendChild(tsSource);
            tsMessge.appendChild(tsTranslation);

            if(bFirstEnterText) {
                bFirstEnterText = false;
                tsTextContext.appendChild(tsName);
            }
            tsTextContext.appendChild(tsMessge);
        }
     }

     if(tsMenuContext.hasChildNodes()) {
        tsRoot.appendChild(tsMenuContext);
     }
     if(tsStringContext.hasChildNodes()) {
         tsRoot.appendChild(tsStringContext);
     }
     if(tsTextContext.hasChildNodes()) {
         tsRoot.appendChild(tsTextContext);
     }

    tsDoc.appendChild(tsRoot);

    QFile file(ts_file);
    if (!file.open(QIODevice::WriteOnly | QFile::Truncate)) {
         return false;
    }
    QTextStream out(&file);
    out.setCodec("UTF-8");
    out << tsDoc.toByteArray();
    file.close();
    return true;
}

bool ParseXmlData::readXlsxFile(const QString& xlsx_file)
{
    m_vector.clear();
    XLDocument doc;
    doc.open(xlsx_file.toStdString());
    auto wks = doc.workbook().worksheet("Sheet1");

    int idx = 2;
    std::string rowColum = QString("A%1").arg(idx).toStdString();
    while(!wks.cell(rowColum).value().getString().empty()) {
        TranslateMessage message;
        message.source = QString::fromStdString(wks.cell(rowColum).value().getString());
        rowColum = QString("B%1").arg(idx).toStdString();
        message.translation = QString::fromStdString(wks.cell(rowColum).value().getString());
        rowColum = QString("C%1").arg(idx).toStdString();
        message.name = QString::fromStdString(wks.cell(rowColum).value().getString());
        rowColum = QString("D%1").arg(idx).toStdString();
        message.stringToLcation(QString::fromStdString(wks.cell(rowColum).value().getString()));
        m_vector.push_back(message);
        idx++;
        rowColum = QString("A%1").arg(idx).toStdString();
    }

    doc.save();
    doc.close();
    return true;
}

bool ParseXmlData::writeXlsxFile(const QString &xlsx_file) {
    XLDocument doc;
    doc.create(xlsx_file.toStdString());
    auto wks = doc.workbook().worksheet("Sheet1");

    wks.cell("A1").value() = "source";
    wks.cell("B1").value() = "translation";
    wks.cell("C1").value() = "name";
    wks.cell("D1").value() = "location";

    for(auto idx = 0; idx < m_vector.size(); idx++) {
        std::string rowColum = QString("A%1").arg(idx+2).toStdString();
        wks.cell(rowColum).value() = m_vector[idx].source.toStdString();
        rowColum = QString("B%1").arg(idx+2).toStdString();
        wks.cell(rowColum).value() = m_vector[idx].translation.toStdString();
        rowColum = QString("C%1").arg(idx+2).toStdString();
        wks.cell(rowColum).value() = m_vector[idx].name.toStdString();
        rowColum = QString("D%1").arg(idx+2).toStdString();
        wks.cell(rowColum).value() = m_vector[idx].locationToString().toStdString();
    }

    doc.save();
    doc.close();
    return true;
}

//bool ParseXmlData::writeCsvFile(const QString &csv_file) {
//    QFile file(csv_file);
//    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
//        return false;
//    }

//    QTextStream out(&file);
//    out << "source" << "," << "translation" << "," << "name" << "," << "location" << "\n";
//    for(auto idx = 0; idx < m_vector.size(); idx++) {

//        out << "\"" << m_vector[idx].source << "\"" << "," << m_vector[idx].translation << "," << m_vector[idx].name << "," \
//            << m_vector[idx].locationToString()<< "\n";
//    }

//    file.close();

//    return true;
//}


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_parseXml = new ParseXmlData(this);
//    TranslateMessage message;
//    LocationInfo info;
//    info.filename = "caaaaaa";
//    info.line = "10001";
//    message.locationInfo.push_back(info);
//    info.filename = "bbbbbb";
//    info.line = "10002";
//    message.locationInfo.push_back(info);
//    info.filename = "aCCCCCC";
//    info.line = "10003";
//    message.locationInfo.push_back(info);
//    auto result = message.locationToString();
//    qDebug() << result;
//    TranslateMessage message2;
//    message2.stringToLcation(result);
//    m_parseXml->parseTsFile("C:/Users/sodawang/Documents/mulLanguageTool/MultiLanguageTool/translation_de.ts");
//    m_parseXml->writeXlsxFile("C:/Users/sodawang/Documents/mulLanguageTool/MultiLanguageTool/translation_de.xlsx");
    this->setWindowTitle(QStringLiteral("多语言工具"));
    for(auto& key : g_mapTsName.keys()) {
        ui->comboBox->addItem(key);
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(nullptr, QObject::tr("Open File"),
                                                    "/home",
                                                    tr("ts Files (*.ts);;"));

    if (!filePath.isEmpty()) {
        ui->lineEdit->setText(filePath);
        QFileInfo info(ui->lineEdit->text());
        ui->lineEdit_2->setText(info.absolutePath() + "/" + info.completeBaseName() + ".xlsx");
    }
}

void MainWindow::on_pushButton_3_clicked()
{
    if(ui->lineEdit->text().isEmpty()) {
        QMessageBox::information(this, QStringLiteral("错误"), QStringLiteral("请选择ts文件！"));
        return;
    }

    m_parseXml->parseTsFile(ui->lineEdit->text());
    QFileInfo info(ui->lineEdit->text());
    m_parseXml->writeXlsxFile(ui->lineEdit_2->text());
    QMessageBox::information(this, QStringLiteral("成功"), QStringLiteral("xlsx 文件成功生成!"));
}

void MainWindow::on_pushButton_5_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(nullptr, QStringLiteral("打开文件"),
                                                    "/home",
                                                    tr("xlsx Files (*.xlsx);;"));

    if (!filePath.isEmpty()) {
        ui->lineEdit_3->setText(filePath);
        QFileInfo info(ui->lineEdit_3->text());
        ui->lineEdit_4->setText(info.absolutePath() + "/" + info.completeBaseName() + ".ts");
    }
}


void MainWindow::on_pushButton_6_clicked()
{
    if(ui->lineEdit_3->text().isEmpty()) {
        QMessageBox::information(this, QStringLiteral("错误"), QStringLiteral("选择一个xlsx文件!"));
        return;
    }

    m_parseXml->readXlsxFile(ui->lineEdit_3->text());
    m_parseXml->writeTsFile(ui->lineEdit_4->text());
    QMessageBox::information(this, QStringLiteral("成功"), QStringLiteral("ts 文件成功生成!"));
}


void MainWindow::on_pushButton_7_clicked()
{
    QProcess myProcess;
    QFile info(QApplication::applicationDirPath() + "/lupdate.exe");
    if(!info.exists()) {
        QMessageBox::information(this, QStringLiteral("错误"), QStringLiteral("缺少lupdate文件!"));
        return;
    }

    int count = ui->listWidget->count();
    if(count <= 0) {
        QMessageBox::information(this, QStringLiteral("错误"), QStringLiteral("请选择翻译的路径!"));
        return;
    }

    QStringList listArgs;
    for (int i = 0; i < count; ++i) {
        QListWidgetItem *item = ui->listWidget->item(i);
        listArgs << item->text();
    }
    listArgs << "-ts";
    if(g_mapTsName.value(ui->comboBox->currentText()).isEmpty()) {
        QMessageBox::information(this, QStringLiteral("错误"), QStringLiteral("未找到语言!"));
        return;
    }

    listArgs << ui->lineEdit_5->text() + "/" + g_mapTsName.value(ui->comboBox->currentText());
    qDebug() << info.fileName();
    qDebug() << listArgs;
    myProcess.setProgram(info.fileName());
    myProcess.setArguments(listArgs);
    myProcess.start();
    myProcess.waitForFinished();
    QMessageBox::information(this, QStringLiteral("成功"), QStringLiteral("ts 文件成功生成!"));
}


void MainWindow::on_pushButton_2_clicked()
{
    QStringList filePaths = QFileDialog::getOpenFileNames(nullptr, QObject::tr("Open File"),
                                                    "/home",
                                                    tr("All Files (*.*);;"));

    if (filePaths.size() > 0) {
        ui->listWidget->addItems(filePaths);
        QFileInfo info(filePaths.at(0));
        ui->lineEdit_5->setText(info.absolutePath());
    }
}


void MainWindow::on_pushButton_4_clicked()
{
    ui->listWidget->clear();
}

